package org.xx.armory.db.junit;

import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static org.xx.armory.commons.Validators.notNull;

/**
 * 从XML文件中读取数据库记录的类
 *
 * @author Haart
 */
public abstract class DbUnitTableReader {
    private static final String ROOT_ELEMENT_NAME = "rows";
    private static final String ROW_ELEMENT_NAME = "row";

    /**
     * 构造DbUnitTableReader类型的实例。
     */
    private DbUnitTableReader() {
    }

    /**
     * 从XML文件中读取指定数据库表的记录
     *
     * @param stream
     *         包含XML文件的流
     * @return 成功读取的记录列表, 每条记录是一个{@code java.util.Map<String, String>}类型的变量。
     * @throws NullPointerException
     *         如果参数{@code tableName}是{@code null}或者参数{@code stream}是{@code null}。
     * @throws XMLStreamException
     *         如果创建{@code javax.xml.stream.XMLStreamReader}对象时出现错误或者从XML文件中读取数据时出现错误。
     */
    public static Collection<Map<String, String>> read(
            InputStream stream
    )
            throws XMLStreamException {
        notNull(stream, "stream");

        final List<Map<String, String>> ret = new ArrayList<>();

        final XMLStreamReader reader = XMLInputFactory.newFactory().createXMLStreamReader(stream);

        for (; ; ) {
            while (!reader.isStartElement()
                    || !ROW_ELEMENT_NAME.equalsIgnoreCase(reader.getLocalName())) {
                if (reader.isEndElement()
                        && ROOT_ELEMENT_NAME.equalsIgnoreCase(reader.getLocalName())) {
                    break;
                }
                reader.next();
            }

            if (reader.isEndElement() && ROOT_ELEMENT_NAME.equalsIgnoreCase(reader.getLocalName())) {
                break;
            }

            ret.add(readRow(reader));
        }

        return Collections.unmodifiableCollection(ret);
    }

    /**
     * 从XML文件中读取指定数据库表的一条记录
     *
     * @param reader
     *         用于读取XML文件的XML流读取器
     * @return 读到的一条记录。
     * @throws NullPointerException
     *         如果参数{@code reader}是{@code null}。
     * @throws XMLStreamException
     *         如果从XML文件中读取数据时出现错误。
     */
    public static Map<String, String> readRow(
            XMLStreamReader reader
    )
            throws XMLStreamException {
        notNull(reader, "reader");

        final Map<String, String> ret = new HashMap<>();

        final long ac = reader.getAttributeCount();
        for (int i = 0; i < ac; ++i) {
            ret.put(reader.getAttributeLocalName(i), reader.getAttributeValue(i));
        }

        // Skip whole row.
        reader.getElementText();

        return Collections.unmodifiableMap(ret);
    }

}
